package com.hsmpay.yl8583.service;

import com.hsmpay.utils.DesUtil;
import com.hsmpay.utils.WriteFile;
import com.hsmpay.utils.system.ConConfig;
import com.hsmpay.yl8583.utils.TestDes;
import com.iso8583.Iso8583Composer;
import com.iso8583.Iso8583Parser;
import com.iso8583.util.ByteUtils;
import com.iso8583.util.J8583Util;
import com.iso8583.util.PosUtil;
import org.apache.commons.lang.StringUtils;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Administrator on 2015/7/7.
 */
public class EPointToBoss {
    static WriteFile wf = new WriteFile("ds_EPoint");
    public static String debug = ConConfig.getAttribute("EPOINT-DAISHOU-DEBUG-STATUS");
    static String ipAddr = "36.250.6.230";
    static Integer iPort = 48010;
    String itimeout = "60000";
    String ShopCode = "780421358120001";//商户号
    String PosNo = "35000152";//终端号
    String tpdu = "6010011002";//tpdu
    String header = "603100311004";//header
    String batch = "000002";// 批次号
    String serialNumber = "000002"; // 系统跟踪号(POS中心流水号)
    String operator = "001";//操作员
    String bit32 = "00000000";//受理方标识码(1-4位:机构代码，5-8位:地区代码)
    String bit62 = "0000000000000000000000000000000";//订单支付信息(订单号n20+手机号n11)
    String PinKey = "FDB1E94CBB8C932E8A72238D308D2B85";
    //封顶密文报文密钥
    String MacKey = "47C0168CAAD727A747C0168CAAD727A7";
    //磁道密钥
    String trkKey = "E935019CD220F6B2F95529E8D5A15D03";
    //母POS密钥
    String MasterKey = "AC251AD8EBB402054A8DF63FE0CDCD88";//密文
    //判断是否为生产环境
    static {
        if ("1".equals(debug)) {//生产环境
            ipAddr = "36.250.6.230";
            iPort = 48010;
        }
    }
    /**
     * 构造函数
     *
     * @param ShopCode
     * @param PosNo
     * @param batch
     * @param MasterKey
     * @param PinKey
     * @param MacKey
     * @param trkKey
     */
    public EPointToBoss(String ShopCode, String PosNo, String batch, String MasterKey, String PinKey, String MacKey, String trkKey) {
        this.ShopCode = ShopCode;
        this.PosNo = PosNo;
        this.batch = batch;
        this.MasterKey = DesUtil.decode3DES(MasterKey, "11111111111111111111111111111111");
        this.PinKey = PinKey;
        this.MacKey = MacKey;
        this.trkKey = trkKey;
        if (null != batch && StringUtils.isEmpty(batch.trim())) {
            this.batch = "000001";
        }
//        if (null != MasterKey && StringUtils.isNotEmpty(MasterKey.trim())) {
//            this.MasterKey = DesUtil.decode3DES(MasterKey,"11111111111111111111111111111111");
//        }
        wf.log("tpdu:" + this.tpdu, "调试");
        wf.log("ShopCode(商户号):" + this.ShopCode, "调试");
        wf.log("PosNo(终端号):" + this.PosNo, "调试");
        wf.log("batch(批次号):" + this.batch, "调试");
        wf.log("MasterKey:" + this.MasterKey, "调试");
        wf.log("PinKey:" + this.PinKey, "调试");
        wf.log("MacKey:" + this.MacKey, "调试");
        wf.log("trkKey:" + this.trkKey, "调试");
    }
    /**
     * 终端签到
     *
     * @return 批次号
     * @throws Exception
     */
    public String Login0800(String serialNumber) throws Exception {
        String LoginMsg = "";
        String TYPE_ID = "0800";
        String mustFields = "";
        HashMap<String,String> body = new HashMap<String,String>();
        wf.log("-------------------请求包域值信息-------------------", "调试");
        body.put("TPDU", this.tpdu);
        body.put("HEAD", this.header);
        body.put("CSEQ_NO", serialNumber);
        body.put("TRM_NO", this.PosNo);
        body.put("MERC_CD", this.ShopCode);
        body.put("RESE_PRI_60", "00" + this.batch + "003");
        body.put("RESE_PRI_62","53657175656E6365204E6F3132333131383739323138363833");
        //body.put("RESE_PRI_62", "16H7NL00717784");
        //body.put("RESE_PRI_62", "16ABCD000000030676");
        body.put("RESE_PRI_63", this.operator);
        String optionalFields = "11|41|42|60|62|63";
        //生成报文
        System.out.println("e点签到生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optionalFields, TYPE_ID, body, "pos", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage, false);//此处false代表加不加空格
        wf.log("e点签到请求报文为：" + req, "调试");
        System.out.println("e点签到请求报文为：" + req);
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, this.ipAddr, this.iPort);
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("e点签到响应报文是：" + res);
        wf.log("e点签到响应报文为：" + res, "调试");
        try {
            //解析报文
            byte[] bytes = ByteUtils.hexStringToByte(res);
            Map<String, String> map = Iso8583Parser.parse("POS", bytes, true);
            //处理解析的map
            //分别获取39,60,62域
            String bit39 = map.get("39");
            String bit60 = map.get("60");
            String bit62 = map.get("62");
            System.out.println("bit62----->" +bit62);
            String PIK = bit62.substring(2,34);
            String PIK_check_bit = bit62.substring(34, 42);
            String MAK = bit62.substring(42,74);
            MAK = MAK.replace("0000000000000000", MAK.substring(0, 16));
            String MAK_check_bit = bit62.substring(74, 82);
            String TDK = bit62.substring(82, 114);
            String TDK_check_bit = bit62.substring(114);

            // DesUtil.compute3DES(DesUtil.hexStringToByte("0000000000000000"), DesUtil.hexStringToByte())
            String decodedPIK = DesUtil.decode3DES(PIK, MasterKey);
            String decodedMAK = DesUtil.decode3DES(MAK, MasterKey);
            String decodedTDK = DesUtil.decode3DES(TDK, MasterKey);
            String temp1 = DesUtil.encrypt3DES("0000000000000000", decodedPIK);
            String temp2 = DesUtil.encrypt3DES("0000000000000000", decodedMAK);
            String temp3 = DesUtil.encrypt3DES("0000000000000000", decodedTDK);

            System.out.println("签到得到的trk" + bit62.substring(80));
            System.out.println("PIK: " + PIK + "\t" + "decoded: " + decodedPIK + "\t" + PIK_check_bit + "\t" + temp1);
            System.out.println("MAK: " + MAK + "\t" + "decoded: " + decodedMAK + "\t" + MAK_check_bit + "\t" + temp2);
            System.out.println("TDK: " + TDK + "\t" + "decoded: " + decodedTDK + "\t" + TDK_check_bit + "\t" + temp3);
            LoginMsg = "0_"+ bit39+ "_" + bit60 + "_" + PIK + "_" + MAK + "_" + TDK;
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("e点签到返回报文解析报文错误");
            wf.log("e点签到返回报文解析错误" ,"调试");
        }
        return LoginMsg;
    }
    /**
     * 银行卡余额查询
     *
     * @param trk2 二磁道数据
     * @param trk3 二磁道数据
     * @param pin  卡交易密码
     * @param accountNumber 主账号
     * @param serialNumber 受卡方系统跟踪号
     * @return 订单信息
     * @throws Exception
     */
    public String Query(String trk2, String trk3, String pin, String accountNumber, String serialNumber, String bit23, String bit55, String bit14) throws Exception {
        String MasterKey = this.MasterKey;
        String PIK = this.PinKey;
        String MAK = DesUtil.decode3DES(this.MacKey, MasterKey);
        String TDK = DesUtil.decode3DES(this.trkKey, MasterKey);
        String des_pin = TestDes.MakeDesPin(accountNumber, pin, PIK, MasterKey);
        String QueryMsg = "";
        String TYPE_ID = "0200";
        String mustFields = "";
        StringBuffer optionalFields = new StringBuffer("");
        HashMap<String,String> body = new HashMap<String,String>();
        wf.log("-------------------请求包域值信息-------------------", "调试");
        body.put("TPDU", this.tpdu);
        body.put("HEAD", this.header);
        body.put("PAN", accountNumber);
        optionalFields.append("2|");
        body.put("PRO_COD", "300000");
        optionalFields.append("3|");
        body.put("CSEQ_NO", serialNumber);
        System.out.println("e点终端流水号：" + serialNumber);
        optionalFields.append("11|");
        if (!"".equals(bit14.trim())) {
            body.put("EXP_DT", bit14);
            optionalFields.append("14|");
        }
        if ("".equals(bit55.trim())) {
            body.put("IN_MOD", "021");
            optionalFields.append("22|");
        }else {
            body.put("IN_MOD", "051");
            optionalFields.append("22|");
        }
        if (!"".equals(bit23.trim())) {
            body.put("SEP_NUM", bit23);
            optionalFields.append("23|");
        }
        body.put("CON_MOD", "00");
        optionalFields.append("25|");
        body.put("PIN_CAP_CODE", "06");
        optionalFields.append("26|");
        if (!"".equals(trk2.trim())) {
            System.out.println("加密前的trk2为：" + trk2);
            //对后16位加密
            trk2 = DesUtil.newEncryptStanderTranck(TDK, trk2).substring(2);
            //替换掉原trk 数据的后16位
            body.put("TRACK_2", trk2);
            System.out.println("加密截取后的trk2为：" + trk2);
            optionalFields.append("35|");
        }
        if (!"".equals(trk3.trim())) {
            trk3 = DesUtil.newEncryptStanderTranck(TDK, trk3).substring(2);
            body.put("TRACK_3", trk3);
            optionalFields.append("36|");
        }
        body.put("TRM_NO", this.PosNo);
        optionalFields.append("41|");
        body.put("MERC_CD", this.ShopCode);
        optionalFields.append("42|");
        body.put("CCY", "156");
        optionalFields.append("49|");
        body.put("PIN_DATA", des_pin);
        optionalFields.append("52|");
        body.put("SECUR_INF", "2600000000000000");
        optionalFields.append("53|");
        if (!"".equals(bit55.trim())) {
            body.put("IC_DAT", bit55);
            optionalFields.append("55|");
        }
        if ("".equals(bit55.trim())) {
            body.put("RESE_PRI_60", "01" + this.batch);
            optionalFields.append("60");
        }else {
            body.put("RESE_PRI_60", "01" + this.batch + "00050");
            optionalFields.append("60");
        }
        optionalFields.append("|64");
        body.put("F64","");
        Iso8583Composer com = new Iso8583Composer();
        byte[] MacMessage = com.compose(mustFields, optionalFields.toString(), TYPE_ID, body, "pos", true);
        String request = ByteUtils.byte2HexStr(MacMessage,false);
        String sub = request.substring(22);
        String macstr = TestDes.MakeECBMac(MAK, sub, null);//加密操作,传参问题
        body.put("F64", macstr);
        System.out.println("optionalFields " + optionalFields.toString());
        //生成报文
        System.out.println("e点查询余额生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optionalFields.toString(), TYPE_ID, body, "pos", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        //PosUtil.analysis8583(req);//解析请求报文
        wf.log("e点查询余额请求报文为：" + req, "调试");
        System.out.println("e点查询余额请求报文为：" + req);
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ipAddr, iPort);
        String res = ByteUtils.byte2HexStr(response, false);
        if ((!"-1".equals(res)) && (!"".equals(res))) {
            System.out.println("e点查询余额响应报文是：" + res);
            wf.log("e点查询余额响应报文为：" + res, "调试");
            try {
                PosUtil.analysis8583(res);
                //解析报文
                Map<String, String> map = Iso8583Parser.parse("POS", response, true);
                //获取39、54域
                String result39 = map.get("39");
                if ("00".equals(result39)){
                    String result54 = map.get("54");
                    String AmountStr = handle54(result54);
                    QueryMsg = "0" + "_" + result39 + "_" + AmountStr;
                }else {
                    QueryMsg = "0" + "_" + result39;
                }
                //获取域值信息，处理返回数据
            }catch (Exception e) {
                e.printStackTrace();
                System.out.println("e点查询余额解析错误");
                wf.log("e点查询余额解析错误", "调试");
            }
        }else {
            QueryMsg = "-1_";
        }
        wf.log("e点佘额查询返回数据:" + QueryMsg, "调试");
        return QueryMsg;
    }
    /**
     * 处理54域信息的方法
     */
    public String  handle54(String field54){
        String ACCOUNT_TYPE="";		//帐户类型(10:储蓄帐户,30:信用卡帐户)
        //String AMOUNT_TYPE="";		//数量类型(02:可用佘额)
        String CURRENCY_CODE="";	//货币代码(156:人民币,其它:美元)
        String AMOUNT_SIGN="";		//余额符号(C:正,其它:负)
        Double AMOUNT=0.00;			//佘额(12位表示,分为单位)
        String AmountStr="";
        ACCOUNT_TYPE=field54.substring(0, 2);
        //AMOUNT_TYPE=value.substring(2, 4);
        CURRENCY_CODE=field54.substring(4,7);
        AMOUNT_SIGN=field54.substring(7, 8);
        AMOUNT=Double.parseDouble(field54.substring(8))/100;
        if(ACCOUNT_TYPE.equals("10"))
        {
            AmountStr+="储蓄帐户 ";
        }else if(ACCOUNT_TYPE.equals("30"))
        {
            AmountStr+="信用卡帐户 ";
        }
        if(CURRENCY_CODE.equals("156"))
        {
            AmountStr+="￥";
        }else{
            AmountStr+="$";
        }
        if(!AMOUNT_SIGN.equals("C"))
        {
            AmountStr+="-";
        }
        AmountStr+=AMOUNT;
        return AmountStr;
    }
    /**
     * 消费
     *
     * @param trk2          二磁道数据
     * @param trk3          三磁道数据
     * @param pin           密码
     * @param money         交易金额
     * @param accountNumber 卡号
     * @param serialNumber  订单号
     * @param bit23         IC卡序列号
     * @param bit55         IC卡 55 域
     * @param bit14         IC卡 序列号
     * @return 返回消费相关信息
     * @throws Exception
     */
    public String BillPayment(String trk2, String trk3, String pin, String money, String accountNumber, String serialNumber, String bit23, String bit55, String bit14) throws Exception {
        String MasterKey = this.MasterKey;
        String PIK = this.PinKey;
        String MAK = DesUtil.decode3DES(this.MacKey, MasterKey);
        String TDK = DesUtil.decode3DES(this.trkKey, MasterKey);
        String des_pin = TestDes.MakeDesPin(accountNumber, pin, PIK, MasterKey);
        String comsumeMsg = "";
        String TYPE_ID = "0200";
        String mustFields = "";
        StringBuffer optionalFields = new StringBuffer("");
        HashMap<String,String> body = new HashMap<String,String>();
        wf.log("-------------------请求包域值信息-------------------", "调试");
        body.put("TPDU", this.tpdu);
        body.put("HEAD", this.header);
        body.put("PAN", accountNumber);
        optionalFields.append("2|");
        body.put("PRO_COD", "000000");
        optionalFields.append("3|");
        body.put("TTXN_AMT", money);
        optionalFields.append("4|");
        body.put("CSEQ_NO", serialNumber);
        System.out.println("e点终端交易流水号：" + serialNumber);
        optionalFields.append("11|");
        if (!"".equals(bit14.trim())) {
            body.put("EXP_DT", bit14);
            optionalFields.append("14|");
        }
        if ("".equals(bit55.trim())) {
            body.put("IN_MOD", "021");
            optionalFields.append("22|");
        }else {
            body.put("IN_MOD", "051");
            optionalFields.append("22|");
        }
        if (!"".equals(bit23.trim())) {
            body.put("SEP_NUM", bit23);
            optionalFields.append("23|");
        }
        body.put("CON_MOD", "00");
        optionalFields.append("25|");
        body.put("PIN_CAP_CODE", "06");
        optionalFields.append("26|");
        if (!"".equals(trk2.trim())) {
            System.out.println("trk2....." + trk2);
            trk2 = DesUtil.newEncryptStanderTranck(TDK, trk2).substring(2);
            body.put("TRACK_2", trk2);
            optionalFields.append("35|");
        }
        if (!"".equals(trk3.trim())) {
            trk3 = DesUtil.newEncryptStanderTranck(TDK, trk3).substring(2);
            body.put("TRACK_3", trk3);
            optionalFields.append("36|");
        }
        body.put("TRM_NO", this.PosNo);
        optionalFields.append("41|");
        body.put("MERC_CD", this.ShopCode);
        optionalFields.append("42|");
        body.put("CCY", "156");
        optionalFields.append("49|");
        body.put("PIN_DATA", des_pin);
        optionalFields.append("52|");
        body.put("SECUR_INF", "2600000000000000");
        optionalFields.append("53|");
        if (!"".equals(bit55.trim())) {
            body.put("IC_DAT", bit55);
            optionalFields.append("55|");
        }
        if ("".equals(bit55.trim())) {
            body.put("RESE_PRI_60", "22" + this.batch);
            optionalFields.append("60");
        }else {
            body.put("RESE_PRI_60", "22" + this.batch + "00050");
            optionalFields.append("60");
        }
        /*body.put("RESE_PRI_62", bit62);
        optionalFields.append("62");*/
        optionalFields.append("|64");
        body.put("F64","");
        Iso8583Composer com = new Iso8583Composer();
        byte[] MacMessage = com.compose(mustFields, optionalFields.toString(), TYPE_ID, body, "pos", true);
        String request = ByteUtils.byte2HexStr(MacMessage,false);
        String sub = request.substring(22);
        //63域是否要出现
        String macstr = TestDes.MakeECBMac(MAK, sub, null);//加密操作,传参问题
        body.put("F64", macstr);
        System.out.println("optionalFields " + optionalFields.toString());
        //生成报文
        System.out.println("e点消费生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optionalFields.toString(), TYPE_ID, body, "pos", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        PosUtil.analysis8583(req.substring(4));//解析请求报文
        wf.log("e点消费请求报文为：" + req, "调试");
        System.out.println("e点消费请求报文为：" + req);
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ipAddr, iPort);
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("e点消费响应报文是：" + res);
        wf.log("e点消费响应报文为：" + res, "调试");
        try {
            PosUtil.analysis8583(res);
            //解析报文,返回解析的域map
            Map<String, String> map = Iso8583Parser.parse("pos", response, true);
            //需要获取2,4,11,12,13,14,37,38,39域信息
            String result2 = map.get("2");
            String result4 = map.get("4");
            String result11 = map.get("11");
            String result12 = map.get("12");
            String result13 = map.get("13");
            String result14 = map.get("14");
            String result37 = map.get("37");
            String result38 = map.get("38");
            String result39 = map.get("39");
            comsumeMsg = "0_" + result2 + "_" +result4 + "_" +result11 + "_" + result12 + "_" +result13 + "_" + result14 + "_" +result37 + "_" +result38 +"_"+result39;
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("e点消费响应报文解析错误");
            wf.log("e点消费响应报文解析错误", "调试");
        }
        wf.log("e点消费返回数据:" + comsumeMsg, "调试");
        return comsumeMsg;
    }

    /**
     * 消费冲正（交易）
     *
     * @param trk2 二磁道数据
     * @param trk3 三磁道数据
     * @return 订单信息
     * @throws Exception
     */
    public String unBillPayment(String trk2, String trk3, String money, String accountNumber, String serialNumber, String bit38, String bit23, String bit55, String bit14, String bit39) throws Exception {
        String MasterKey = this.MasterKey;
        String MAK = DesUtil.decode3DES(this.MacKey, MasterKey);
        String QueryMsg = "";
        String typeCode = "0400";//消息类型
        String mustFields = "";
        StringBuffer optinalFields = new StringBuffer("");
        HashMap<String, String> body = new HashMap<String, String>();
        body.put("TPDU", this.tpdu);
        body.put("HEAD",this.header);
        body.put("PAN", accountNumber);//主账号 2
        optinalFields.append("2|");
        body.put("PRO_COD", "000000");//交易处理码 3 跟原交易相同
        optinalFields.append("3|");
        body.put("TTXN_AMT", money);//交易金额 4  跟原交易相同
        optinalFields.append("4|");
        body.put("CSEQ_NO", serialNumber); //受卡方系统跟踪号 同原交易
        optinalFields.append("11|");
        if (!"".equals(bit14)){
            body.put("EXP_DT", bit14);//14
            optinalFields.append("14|");
        }
        if ("".equals(bit55.trim())) {//服务点输入方式码 22 跟原交易相同
            body.put("IN_MOD", "021");
            optinalFields.append("22|");
        }else {
            body.put("IN_MOD", "051");
            optinalFields.append("22|");
        }
        if (!"".equals(bit23)){
            body.put("SEP_NUM", bit23);
            optinalFields.append("23|");
        }
        body.put("CON_MOD", "00");//服务点条件码 25
        optinalFields.append("25|");
//        body.put("PIN_CAP_CODE", "06");
//        optinalFields.append("26|");//服务点PIN获取码 26
        //38域需要判断应答码中是否存在
        if (StringUtils.isNotBlank(bit38)){
            body.put("AUT_CD", bit38);//授权标识应答码 38 如果原始交易的应答中有授权码，则须填入原交易授权码 从响应报文中获取
            optinalFields.append("38|");
        }
        body.put("CPSCOD",bit39);//应答码 39 请求时为冲正原因，见注  交易报文中获取
        optinalFields.append("39|");
        body.put("TRM_NO", this.PosNo);//受卡机终端标识码 41 同原消费交易
        optinalFields.append("41|");
        body.put("MERC_CD", this.ShopCode);//受卡方标识码 42
        optinalFields.append("42|");
        body.put("CCY", "156");//交易货币代码 49
        optinalFields.append("49|");
        if (!"".equals(bit55)){
            body.put("IC_DAT",bit55);//交易货币代码 49
            optinalFields.append("55|");
        }
        if ("".equals(bit55.trim())) {
            body.put("RESE_PRI_60", "22" + this.batch);
            optinalFields.append("60|");
        }else {
            body.put("RESE_PRI_60", "22" + this.batch + "00050");
            optinalFields.append("60|");
        }
        SimpleDateFormat simple = new SimpleDateFormat("MMdd");
        String date = simple.format(new Date());
        body.put("ORI_MES", this.batch + serialNumber + date);
        optinalFields.append("61|");
        optinalFields.append("64");
        body.put("F64", "");
        Iso8583Composer com = new Iso8583Composer();
        byte[] MacMessage = com.compose(mustFields, optinalFields.toString(), typeCode, body, "pos", true);
        String request = ByteUtils.byte2HexStr(MacMessage,false);
        String sub = request.substring(22);
        String macstr = TestDes.MakeECBMac(MAK, sub, null);//加密操作,传参问题
        body.put("F64", macstr);
        System.out.println("optionalFields " + optinalFields.toString());
        //生成报文
        System.out.println("e点消费冲正生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optinalFields.toString(), typeCode, body, "pos", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        wf.log("e点消费冲正请求报文为：" + req, "调试");
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ipAddr, iPort);
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("e点消费冲正响应报文是：" + res);
        wf.log("e点消费冲正响应报文为：" + res, "调试");
        try {
            PosUtil.analysis8583(res);
            //解析报文
            byte[] bytes = ByteUtils.hexStringToByte(res);
            Map<String, String> map = Iso8583Parser.parse("POS", bytes, true);
            //处理2,4,11,12,13,14,37,38,39,44,61域信息
            String temp2 = map.get("2");
            String temp4 = map.get("4");
            String temp11 = map.get("11");
            String temp12 = map.get("12");
            String temp13 = map.get("13");
            String temp14 = map.get("14");
            String temp37 = map.get("37");
            String temp38 = map.get("38");
            String temp39 = map.get("39");
            String temp44 = map.get("44");
            String temp61 = map.get("61");
            QueryMsg = temp2+"_"+temp4+"_"+temp11+"_"+temp12+"_"+temp13+"_"+temp14+"_"+temp37+"_"+temp38+"_"+temp39+"_"+temp44+"_"+temp61;
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("e点消费冲正响应报文解析错误");
            wf.log("e点消费冲正响应报文解析错误", "调试");
        }
        wf.log("e点消费冲正返回数据:" + QueryMsg, "调试");
        return QueryMsg;
    }

    /**
     * 结算
     * @return
     */
    public String balance(String serialNumber) throws Exception{
        String balance = "";
        String typeCode = "0500";//消息类型
        String mustFields = "";
        HashMap<String, String> body = new HashMap<String, String>();
        StringBuffer optionalFields = new StringBuffer("");
        body.put("TPDU",this.tpdu);//TPDU
        body.put("HEAD", this.header);//HEAD
        body.put("CSEQ_NO", serialNumber);// POS终端交易流水号 11
        optionalFields.append("11|");
        body.put("TRM_NO", this.PosNo);//受卡机终端标识码 41
        optionalFields.append("41|");
        body.put("MERC_CD", this.ShopCode);//受卡方标识码 42
        optionalFields.append("42|");
        body.put("PRI_USE","");//附加数据-私有 48 结算总额，具体见域说明

        body.put("CCY","156");//交易货币代码 49
        optionalFields.append("49|");
        body.put("RESE_PRI_60","00" +this.batch + "201");//自定义域 60   60.1交易类型码(填00) 60.2批次号 60.3网络管理信息码(填201)
        optionalFields.append("60|");
        body.put("RESE_PRI_63",this.operator);//自定义域 63   63.1操作员代码
        optionalFields.append("63");
        System.out.println("optionalFields " + optionalFields.toString());
        //生成报文
        System.out.println("e点批结算生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optionalFields.toString(), typeCode, body, "pos", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        wf.log("e点批结算请求报文为：" + req, "调试");
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ipAddr, iPort);
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("e点批结算响应报文是：" + res);
        wf.log("e点批结算响应报文为：" + res, "调试");
        try {
            //解析报文
            byte[] bytes = ByteUtils.hexStringToByte(res);
            Map<String, String> map = Iso8583Parser.parse("POS", bytes, true);
            //获取域值信息，处理返回数据 38域 用于冲正
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("e点批结算响应报文解析错误");
            wf.log("e点批结算响应报文解析错误", "调试");
        }
        wf.log("e点批结算返回数据:" + balance, "调试");
        return balance;
    }
    /**
     * 消费撤销
     * @return
     */
    public String cancelConsumption(String trk2, String trk3, String pin, String bit14, String bit23, String bit35, String bit36, String bit38, String bit55, String accountNumber, String money) throws Exception{
        String des_pin = TestDes.MakeDesPin(accountNumber, pin, PinKey, MasterKey);
        String cancel = "";
        String typeCode = "0200";//消息类型
        String mustFields = "";
        HashMap<String, String> body = new HashMap<String, String>();
        StringBuffer optionalFileds = new StringBuffer("");
        body.put("TPDU",this.tpdu);
        body.put("HEAD",this.header);
        body.put("PAN", accountNumber);//主账号 2
        optionalFileds.append("2|");
        body.put("PRO_COD", "200000");//交易处理码 3
        optionalFileds.append("3|");
        body.put("TTXN_AMT", money);//交易金额 4
        optionalFileds.append("4|");
        body.put("CSEQ_NO", serialNumber); // POS终端交易流水号 11
        optionalFileds.append("11|");
        if ("".equals(bit55.trim())) {//服务点输入方式码 22
            body.put("IN_MOD", "021");
            optionalFileds.append("22|");
        }else {
            body.put("IN_MOD", "051");
            optionalFileds.append("22|");
        }
        body.put("CON_MOD","00");//服务点条件码 25
        optionalFileds.append("25|");
        body.put("PIN_CAP_CODE", "26");//服务点PIN获取码 26
        optionalFileds.append("26");
        //二磁道 35
        if (!"".equals(trk2.trim())) {
            trk2 = DesUtil.newEncryptStanderTranck(trkKey, trk2).substring(2);
            body.put("TRACK_2", trk2);
            optionalFileds.append("35|");
        }
        body.put("RET_RE_NO","");//检索参考号 37 请求时为原消费交易参考号 从返回报文中获取
        optionalFileds.append("37|");
        body.put("AUT_CD", "");//授权标识应答码 38 如果原始交易的应答中有授权码，则须填入原交易授权码 需要做判断
        body.put("TRM_NO",this.PosNo);//受卡机终端标识码 41 同原消费交易
        optionalFileds.append("41|");
        body.put("MERC_CD", this.ShopCode);//受卡方标识码 42
        optionalFileds.append("42|");
        body.put("CCY", "156");//交易货币代码 49
        optionalFileds.append("49|");
        //自定义域 60 自定义域  包含子域
        if ("".equals(bit55.trim())) {
            body.put("RESE_PRI_60", "01" + this.batch);
            optionalFileds.append("60|");
        }else {
            body.put("RESE_PRI_60", "01" + this.batch + "00050");
            optionalFileds.append("60|");
        }
        body.put("ORI_MES",this.batch + this.serialNumber);//原始信息域 61
        optionalFileds.append("61|");
        body.put("F64","");//MAC 64
        String optionalFields = "2|3|4|11|22|25|26|35|37|38|41|42|49|60|61|64"; //不包括第0域和bitMap
        String macstr = TestDes.MakeECBMac(MacKey, "", MasterKey);//加密操作,传参问题
        body.put("F64", macstr);
        optionalFileds.append("64");
        System.out.println("optionalFields " + optionalFields.toString());
        //生成报文
        System.out.println("e点消费撤销生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.compose(mustFields, optionalFields.toString(), typeCode, body, "pos", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        wf.log("e点消费撤销请求报文为：" + req, "调试");
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ipAddr, iPort);
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("e点消费撤销响应报文是：" + res);
        wf.log("e点消费撤销响应报文为：" + res, "调试");
        try {
            //解析报文
            byte[] bytes = ByteUtils.hexStringToByte(res);
            Map<String, String> map = Iso8583Parser.parse("POS", bytes, true);
            //获取域值信息，处理返回数据
            PosUtil.analysis8583(res);
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("e点消费撤销响应报文解析错误");
            wf.log("e点消费撤销响应报文解析错误", "调试");
        }
        wf.log("e点消费撤销返回数据:" + cancel, "调试");

        return cancel;
    }
    public static void main(String [] argus) throws Exception {
        String req = "601001100260310031192308000020000000C0001600016836313030353539383738303631303135373232313135390011000000170040002553657175656E6365204E6F31323331313837393231383638330003303120\n";
        PosUtil.analysis8583(req);
    }
}